<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>玩转仿探探卡片式滑动效果 | 不忘初心</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="转载： http:&#x2F;&#x2F;yuqirong.me&#x2F;2017&#x2F;03&#x2F;05&#x2F;玩转仿探探卡片式滑动效果    讲起本篇博客的历史起源，估计有一段“历史”了。最早可以追溯到我试玩探探这个 APP 。第一次进入软件界面，就被这种通过卡片式滑动来选择“喜欢&#x2F;不喜欢”的设计所吸引了。当时就非常想通过自己来实现这种仿探探式的效果，然而却没什么思路。不过毋庸置疑的是，这种效果的原理肯定和 ListView &#x2F; Rec">
<meta property="og:type" content="article">
<meta property="og:title" content="玩转仿探探卡片式滑动效果">
<meta property="og:url" content="http://example.com/2017/07/11/RecyclerView/RecyclerView--%E7%8E%A9%E8%BD%AC%E4%BB%BF%E6%8E%A2%E6%8E%A2%E5%8D%A1%E7%89%87%E5%BC%8F%E6%BB%91%E5%8A%A8%E6%95%88%E6%9E%9C/index.html">
<meta property="og:site_name" content="不忘初心">
<meta property="og:description" content="转载： http:&#x2F;&#x2F;yuqirong.me&#x2F;2017&#x2F;03&#x2F;05&#x2F;玩转仿探探卡片式滑动效果    讲起本篇博客的历史起源，估计有一段“历史”了。最早可以追溯到我试玩探探这个 APP 。第一次进入软件界面，就被这种通过卡片式滑动来选择“喜欢&#x2F;不喜欢”的设计所吸引了。当时就非常想通过自己来实现这种仿探探式的效果，然而却没什么思路。不过毋庸置疑的是，这种效果的原理肯定和 ListView &#x2F; Rec">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="http://ofyt9w4c2.bkt.clouddn.com/20170306/20170306221018.jpg">
<meta property="og:image" content="http://ofyt9w4c2.bkt.clouddn.com/20170306/20170307214251.gif">
<meta property="og:image" content="http://ofyt9w4c2.bkt.clouddn.com/20170306/20170307222247.gif">
<meta property="og:image" content="http://ofyt9w4c2.bkt.clouddn.com/20170306/20170306234152.gif">
<meta property="article:published_time" content="2017-07-11T05:27:06.000Z">
<meta property="article:modified_time" content="2018-07-15T07:27:10.000Z">
<meta property="article:author" content="wxyass">
<meta property="article:tag" content="RecyclerView">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://ofyt9w4c2.bkt.clouddn.com/20170306/20170306221018.jpg">
  
    <link rel="alternate" href="/atom.xml" title="不忘初心" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/favicon.png">
  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/typeface-source-code-pro@0.0.71/index.min.css">

  
  
<link rel="stylesheet" href="/css/style.css">

  
    
<link rel="stylesheet" href="/fancybox/jquery.fancybox.min.css">

  
<meta name="generator" content="Hexo 5.4.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">不忘初心</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://example.com"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main"><article id="post-RecyclerView/RecyclerView--玩转仿探探卡片式滑动效果" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/2017/07/11/RecyclerView/RecyclerView--%E7%8E%A9%E8%BD%AC%E4%BB%BF%E6%8E%A2%E6%8E%A2%E5%8D%A1%E7%89%87%E5%BC%8F%E6%BB%91%E5%8A%A8%E6%95%88%E6%9E%9C/" class="article-date">
  <time class="dt-published" datetime="2017-07-11T05:27:06.000Z" itemprop="datePublished">2017-07-11</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/RecyclerView/">RecyclerView</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="p-name article-title" itemprop="headline name">
      玩转仿探探卡片式滑动效果
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <blockquote>
<p>转载： <a target="_blank" rel="noopener" href="http://yuqirong.me/2017/03/05/%E7%8E%A9%E8%BD%AC%E4%BB%BF%E6%8E%A2%E6%8E%A2%E5%8D%A1%E7%89%87%E5%BC%8F%E6%BB%91%E5%8A%A8%E6%95%88%E6%9E%9C">http://yuqirong.me/2017/03/05/玩转仿探探卡片式滑动效果</a>  </p>
</blockquote>
<p>讲起本篇博客的历史起源，估计有一段“历史”了。<br>最早可以追溯到我试玩探探这个 APP 。第一次进入软件界面，就被这种通过卡片式滑动来选择“喜欢/不喜欢”的设计所吸引了。当时就非常想通过自己来实现这种仿探探式的效果，然而却没什么思路。不过毋庸置疑的是，这种效果的原理肯定和 ListView / RecyclerView 类似，涉及到 Item View 的回收和重用，否则早就因为大量的 Item View 而 OOM 了。    </p>
<span id="more"></span>  


<p>再到后来，看到许多大神也推出了同样仿探探效果的博客，从头到尾阅读下来，写得通俗易懂，基本上没什么问题。于是，实现仿探探效果的想法再次出现在脑海中。那么，还犹豫什么，趁热来一发吧！就这么愉快地决定了。</p>
<p>首先面临的问题就是关于实现 View 上的考虑。毫无疑问，</p>
<p><strong>RecyclerView 是最佳选择！</strong></p>
<p><strong>RecyclerView 是最佳选择！</strong></p>
<p><strong>RecyclerView 是最佳选择！</strong></p>
<p>重要的话讲三遍！！！</p>
<p>究其原因，第一，RecyclerView 是自带 Item View 回收和重用功能的，就不需要我们考虑这个问题了；第二，RecyclerView 的布局方式是通过设置 LayoutManager 来实现的，这样就充分地把布局和 RecyclerView “解耦”开来了。而 LayoutManager 是可以通过自定义的方式来实现的。这恰恰是我们想要的！！！再说一点，这也正是不选用 ListView 的原因之一。</p>
<p>下面，我们就开始动手了。带你见证奇迹的时刻。</p>  

<h2 id="CardLayoutManager"><a href="#CardLayoutManager" class="headerlink" title="CardLayoutManager"></a>CardLayoutManager</h2>

<p>创建 <code>CardLayoutManager</code> 并继承自 <code>RecyclerView.LayoutManager</code> 。需要我们自己实现 <code>generateDefaultLayoutParams()</code> 方法：</p>  
 
<pre><code>@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() &#123;
    return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,      ViewGroup.LayoutParams.WRAP_CONTENT);
&#125;  
</code></pre>
<p>一般情况下，像上面这样写即可。</p>
<p>下面这个方法就是我们的重点了。 <code>onLayoutChildren(final RecyclerView.Recycler recycler, RecyclerView.State state)</code> 方法就是用来实现 Item View 布局的：</p>

    
<pre><code>@Override
public void onLayoutChildren(final RecyclerView.Recycler recycler, RecyclerView.State state) &#123;
    super.onLayoutChildren(recycler, state);
    // 先移除所有view
    removeAllViews();
    // 在布局之前，将所有的子 View 先 Detach 掉，放入到 Scrap 缓存中
    detachAndScrapAttachedViews(recycler);
    int itemCount = getItemCount();
    // 在这里，我们默认配置 CardConfig.DEFAULT_SHOW_ITEM = 3。即在屏幕上显示的卡片数为3
    // 当数据源个数大于最大显示数时
    if (itemCount &gt; CardConfig.DEFAULT_SHOW_ITEM) &#123;
        // 把数据源倒着循环，这样，第0个数据就在屏幕最上面了
        for (int position = CardConfig.DEFAULT_SHOW_ITEM; position &gt;= 0; position--) &#123;
            final View view = recycler.getViewForPosition(position);
            // 将 Item View 加入到 RecyclerView 中
            addView(view);
            // 测量 Item View
            measureChildWithMargins(view, 0, 0);
            // getDecoratedMeasuredWidth(view) 可以得到 Item View 的宽度
            // 所以 widthSpace 就是除了 Item View 剩余的值
            int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
            // 同理
            int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);
            // 将 Item View 放入 RecyclerView 中布局
            // 在这里默认布局是放在 RecyclerView 中心
            layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2,
                    widthSpace / 2 + getDecoratedMeasuredWidth(view),
                    heightSpace / 2 + getDecoratedMeasuredHeight(view));
            // 其实屏幕上有四张卡片，但是我们把第三张和第四张卡片重叠在一起，这样看上去就只有三张
            // 第四张卡片主要是为了保持动画的连贯性
            if (position == CardConfig.DEFAULT_SHOW_ITEM) &#123;
                // 按照一定的规则缩放，并且偏移Y轴。
                // CardConfig.DEFAULT_SCALE 默认为0.1f，CardConfig.DEFAULT_TRANSLATE_Y 默认为14
                view.setScaleX(1 - (position - 1) * CardConfig.DEFAULT_SCALE);
                view.setScaleY(1 - (position - 1) * CardConfig.DEFAULT_SCALE);
                view.setTranslationY((position - 1) * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
            &#125; else if (position &gt; 0) &#123;
                view.setScaleX(1 - position * CardConfig.DEFAULT_SCALE);
                view.setScaleY(1 - position * CardConfig.DEFAULT_SCALE);
                view.setTranslationY(position * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
            &#125; else &#123;
                // 设置 mTouchListener 的意义就在于我们想让处于顶层的卡片是可以随意滑动的
                // 而第二层、第三层等等的卡片是禁止滑动的
                view.setOnTouchListener(mOnTouchListener);
            &#125;
        &#125;
    &#125; else &#123;
        // 当数据源个数小于或等于最大显示数时，和上面的代码差不多
        for (int position = itemCount - 1; position &gt;= 0; position--) &#123;
            final View view = recycler.getViewForPosition(position);
            addView(view);
            measureChildWithMargins(view, 0, 0);
            int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
            int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);

            layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2,
                    widthSpace / 2 + getDecoratedMeasuredWidth(view),
                    heightSpace / 2 + getDecoratedMeasuredHeight(view));

            if (position &gt; 0) &#123;
                view.setScaleX(1 - position * CardConfig.DEFAULT_SCALE);
                view.setScaleY(1 - position * CardConfig.DEFAULT_SCALE);
                view.setTranslationY(position * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
            &#125; else &#123;
                view.setOnTouchListener(mOnTouchListener);
            &#125;
        &#125;
    &#125;
&#125;

private View.OnTouchListener mOnTouchListener = new View.OnTouchListener() &#123;

    @Override
    public boolean onTouch(View v, MotionEvent event) &#123;
        RecyclerView.ViewHolder childViewHolder = mRecyclerView.getChildViewHolder(v);
        // 把触摸事件交给 mItemTouchHelper，让其处理卡片滑动事件
        if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) &#123;
            mItemTouchHelper.startSwipe(childViewHolder);
        &#125;
        return false;
    &#125;
&#125;;
</code></pre>
<p>总体来说，<code>CardLayoutManager</code> 主要就是为 Item View 布局，然后根据 <code>position</code> 做相对应的偏差。我们一起来看下完成的效果图：</p>
<p><img src="http://ofyt9w4c2.bkt.clouddn.com/20170306/20170306221018.jpg" alt="layout效果图"></p>
<p>可以看出，大致的效果已经有了。缺少的就是处理触摸滑动事件了。</p>

<h2 id="OnSwipeListener"><a href="#OnSwipeListener" class="headerlink" title="OnSwipeListener"></a>OnSwipeListener</h2><p>在看滑动事件的代码之前，我们先定义一个监听器。主要用于监听卡片滑动事件，代码就如下所示，注释也给出来了。应该都看得懂吧：</p>


<pre><code>public interface OnSwipeListener&lt;T&gt; &#123;

    /**
     * 卡片还在滑动时回调
     *
     * @param viewHolder 该滑动卡片的viewHolder
     * @param ratio      滑动进度的比例
     * @param direction  卡片滑动的方向，CardConfig.SWIPING_LEFT 为向左滑，CardConfig.SWIPING_RIGHT 为向右滑，
     *                   CardConfig.SWIPING_NONE 为不偏左也不偏右
     */
    void onSwiping(RecyclerView.ViewHolder viewHolder, float ratio, int direction);

    /**
     * 卡片完全滑出时回调
     *
     * @param viewHolder 该滑出卡片的viewHolder
     * @param t          该滑出卡片的数据
     * @param direction  卡片滑出的方向，CardConfig.SWIPED_LEFT 为左边滑出；CardConfig.SWIPED_RIGHT 为右边滑出
     */
    void onSwiped(RecyclerView.ViewHolder viewHolder, T t, int direction);

    /**
     * 所有的卡片全部滑出时回调
     */
    void onSwipedClear();

&#125;
</code></pre>
<h2 id="CardItemTouchHelperCallback"><a href="#CardItemTouchHelperCallback" class="headerlink" title="CardItemTouchHelperCallback"></a>CardItemTouchHelperCallback</h2><p>现在，我们可以回过头来看看卡片滑动了。对于 ItemTouchHelper 来处理 Item View 的触摸滑动事件相必都不陌生吧，如果对这方面不太了解的同学可以看一下我之前的博客：<a href="/2017/02/03/RecyclerView实现拖拽排序和侧滑删除/">《RecyclerView实现拖拽排序和侧滑删除》</a>。</p>
<p>我们暂且命名为 CardItemTouchHelperCallback 。对于 ItemTouchHelper.Callback 而言，需要在 <code>getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)</code> 方法中配置 <code>swipeFlags</code> 和 <code>dragFlags</code> 。</p>
<p>具体的方法如下，对于 <code>swipeFlags</code> 只关心左右两个方向：</p>  



<pre><code>@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) &#123;
    int dragFlags = 0;
    int swipeFlags = 0;
    RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
    if (layoutManager instanceof CardLayoutManager) &#123;
        swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
    &#125;
    return makeMovementFlags(dragFlags, swipeFlags);
&#125;
</code></pre>
<p>还有一点需要注意，前面说过，为了防止第二层和第三层卡片也能滑动，因此我们需要设置 <code>isItemViewSwipeEnabled()</code> 返回 false 。</p>  

<pre><code>@Override
public boolean isItemViewSwipeEnabled() &#123;
    return false;
&#125;
</code></pre>
<p>接下来，就是去重写 <code>onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)</code> 和 <code>onSwiped(RecyclerView.ViewHolder viewHolder, int direction)</code> 方法。但是因为在上面我们对于 <code>dragFlags</code> 配置的是 0 ，所以在 <code>onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)</code> 中直接返回 false 即可。</p>

<pre><code>@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) &#123;
    return false;
&#125;
</code></pre>
<p>这样，我们就把目光投向 <code>onSwiped(RecyclerView.ViewHolder viewHolder, int direction)</code> 方法：</p>

    
<pre><code>@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) &#123;
    // 移除之前设置的 onTouchListener, 否则触摸滑动会乱了
    viewHolder.itemView.setOnTouchListener(null);
    // 删除相对应的数据    
    int layoutPosition = viewHolder.getLayoutPosition();
    T remove = dataList.remove(layoutPosition);
    adapter.notifyDataSetChanged();
    // 卡片滑出后回调 OnSwipeListener 监听器
    if (mListener != null) &#123;
        mListener.onSwiped(viewHolder, remove, direction == ItemTouchHelper.LEFT ? CardConfig.SWIPED_LEFT : CardConfig.SWIPED_RIGHT);
    &#125;
    // 当没有数据时回调 OnSwipeListener 监听器
    if (adapter.getItemCount() == 0) &#123;
        if (mListener != null) &#123;
            mListener.onSwipedClear();
        &#125;
    &#125;
&#125;
</code></pre>
<p>写好后，我们先来看看滑动效果：</p>
<p><img src="http://ofyt9w4c2.bkt.clouddn.com/20170306/20170307214251.gif" alt="swipe效果图"></p>
<p>发现还是差了点什么，没错！是缺少了动画。在滑动的过程中我们可以重写 <code>onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
                            float dX, float dY, int actionState, boolean isCurrentlyActive)</code> 方法来添加动画：</p>  


<pre><code>@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
                        float dX, float dY, int actionState, boolean isCurrentlyActive) &#123;
    super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    View itemView = viewHolder.itemView;
    if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) &#123;
        // 得到滑动的阀值
        float ratio = dX / getThreshold(recyclerView, viewHolder);
        // ratio 最大为 1 或 -1
        if (ratio &gt; 1) &#123;
            ratio = 1;
        &#125; else if (ratio &lt; -1) &#123;
            ratio = -1;
        &#125;
        // 默认最大的旋转角度为 15 度
        itemView.setRotation(ratio * CardConfig.DEFAULT_ROTATE_DEGREE);
        int childCount = recyclerView.getChildCount();
        // 当数据源个数大于最大显示数时
        if (childCount &gt; CardConfig.DEFAULT_SHOW_ITEM) &#123;
            for (int position = 1; position &lt; childCount - 1; position++) &#123;
                int index = childCount - position - 1;
                View view = recyclerView.getChildAt(position);
                // 和之前 onLayoutChildren 是一个意思，不过是做相反的动画
                view.setScaleX(1 - index * CardConfig.DEFAULT_SCALE + Math.abs(ratio) * CardConfig.DEFAULT_SCALE);
                view.setScaleY(1 - index * CardConfig.DEFAULT_SCALE + Math.abs(ratio) * CardConfig.DEFAULT_SCALE);
                view.setTranslationY((index - Math.abs(ratio)) * itemView.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
            &#125;
        &#125; else &#123;
            // 当数据源个数小于或等于最大显示数时
            for (int position = 0; position &lt; childCount - 1; position++) &#123;
                int index = childCount - position - 1;
                View view = recyclerView.getChildAt(position);
                view.setScaleX(1 - index * CardConfig.DEFAULT_SCALE + Math.abs(ratio) * CardConfig.DEFAULT_SCALE);
                view.setScaleY(1 - index * CardConfig.DEFAULT_SCALE + Math.abs(ratio) * CardConfig.DEFAULT_SCALE);
                view.setTranslationY((index - Math.abs(ratio)) * itemView.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
            &#125;
        &#125;
        // 回调监听器
        if (mListener != null) &#123;
            if (ratio != 0) &#123;
                mListener.onSwiping(viewHolder, ratio, ratio &lt; 0 ? CardConfig.SWIPING_LEFT : CardConfig.SWIPING_RIGHT);
            &#125; else &#123;
                mListener.onSwiping(viewHolder, ratio, CardConfig.SWIPING_NONE);
            &#125;
        &#125;
    &#125;
&#125;

private float getThreshold(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) &#123;
    return recyclerView.getWidth() * getSwipeThreshold(viewHolder);
&#125;
</code></pre>
<p>现在我们加上动画后，来看看效果：</p>
<p><img src="http://ofyt9w4c2.bkt.clouddn.com/20170306/20170307222247.gif" alt="swipe效果图"></p>
<p>发现还是有问题，第一层的卡片滑出去之后第二层的就莫名其妙地偏了。这正是因为 Item View 重用机制“捣鬼”。所以我们应该在 <code>clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)</code> 方法中重置一下：</p>

<pre><code>@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) &#123;
    super.clearView(recyclerView, viewHolder);
    viewHolder.itemView.setRotation(0f);
&#125;
</code></pre>
<p>大功告成，我们试一下效果：</p>
<p><img src="http://ofyt9w4c2.bkt.clouddn.com/20170306/20170306234152.gif" alt="swipe效果图"></p>
<p>Perfect !</p>
<p>这正是我们梦寐以求的效果。我们终于实现了！！！</p>
<p>总结一下，在这整个代码流程中我们主要是运用了自定义 LayoutManager 以及 ItemTouchHelper.Callback 。总体来说还是比较简单的，相信你已经会啦。</p>
<p>Goodbye ~~</p>
<p>最后，放上 GitHub 地址：<a href="https://github.com/yuqirong/CardSwipeLayout" target="_blank" rel="external">yuqirong/CardSwipeLayout</a></p>   


<p><a target="_blank" rel="noopener" href="http://oss.wxyass.com/wxyass/demo/CardSwipeLayout-master.zip">源码下载</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://example.com/2017/07/11/RecyclerView/RecyclerView--%E7%8E%A9%E8%BD%AC%E4%BB%BF%E6%8E%A2%E6%8E%A2%E5%8D%A1%E7%89%87%E5%BC%8F%E6%BB%91%E5%8A%A8%E6%95%88%E6%9E%9C/" data-id="ckvc340q6003k5dfyaopngntp" data-title="玩转仿探探卡片式滑动效果" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/RecyclerView/" rel="tag">RecyclerView</a></li></ul>

    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/2017/07/24/ListView/ListView--%E8%A7%A3%E5%86%B3ScrollView%E5%B5%8C%E5%A5%97listview%E5%8A%A8%E6%80%81%E8%AE%BE%E7%BD%AE%E9%AB%98%E5%BA%A6%E6%97%B6%EF%BC%8Citem%E9%AB%98%E5%BA%A6%E4%B8%8D%E4%B8%80%E6%A0%B7%E6%97%B6%EF%BC%8C%E6%9C%80%E5%90%8E%E4%B8%80%E4%B8%AAitem%E6%98%BE%E7%A4%BA%E4%B8%8D%E5%AE%8C%E5%85%A8/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          解决ScrollView嵌套listview动态设置高度时，item高度不一样时，最后一个item显示不完全
        
      </div>
    </a>
  
  
    <a href="/2017/07/11/RecyclerView/RecyclerView--5.x%E4%B9%8BRecyclerView%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title">5.x之RecyclerView的简单使用</div>
    </a>
  
</nav>

  
</article>


</section>
        
          <aside id="sidebar">
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Categories</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/Activity/">Activity</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-Studio%E4%BB%8B%E7%BB%8D/">Android Studio介绍</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android%E5%9F%BA%E7%A1%80/">Android基础</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android%E6%A8%A1%E6%9D%BF/">Android模板</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/BaseRecyclerViewAdapterHelper/">BaseRecyclerViewAdapterHelper</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Bug%E9%97%AE%E9%A2%98/">Bug问题</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Button/">Button</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/EditText/">EditText</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Fragment/">Fragment</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Gradle/">Gradle</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/ListView/">ListView</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/MD%E8%AF%AD%E6%B3%95/">MD语法</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/MyEclipse/">MyEclipse</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/OSS/">OSS</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/RecyclerView/">RecyclerView</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/SQL%E5%9F%BA%E7%A1%80/">SQL基础</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/UI%E6%8E%A7%E4%BB%B6/">UI控件</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/View/">View</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/ViewPager/">ViewPager</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/View%E7%AF%87/">View篇</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/as%E6%8A%A5%E9%94%99/">as报错</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/jar%E5%8C%85/">jar包</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/targetSdkVersion/">targetSdkVersion</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E4%B8%83%E7%89%9B%E4%BA%91/">七牛云</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E4%BA%8C%E7%BB%B4%E7%A0%81/">二维码</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%88%A0%E9%99%A4%E5%9B%BE%E7%89%87%E7%BC%93%E5%AD%98/">删除图片缓存</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%8D%87%E7%BA%A7%E6%8A%A5%E9%94%99/">升级报错</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA/">博客搭建</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%8E%BB%E6%8E%89v7%E5%8C%85/">去掉v7包</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%9B%BE%E7%89%87%E5%A4%84%E7%90%86/">图片处理</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%A4%9A%E5%AA%92%E4%BD%93/">多媒体</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%AE%9A%E5%88%B6%E7%B1%BB/">定制类</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%B0%8F%E7%B1%B3%E6%89%8B%E6%9C%BA/">小米手机</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%B9%BF%E6%92%AD%E6%9C%BA%E5%88%B6/">广播机制</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%BE%AE%E5%8D%9A%E5%88%86%E4%BA%AB/">微博分享</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E6%89%93%E5%8C%85APK%E6%8A%A5%E9%94%99/">打包APK报错</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E6%8C%81%E4%B9%85%E5%8C%96%E5%AD%98%E5%82%A8/">持久化存储</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E6%97%B6%E9%97%B4%E9%80%89%E6%8B%A9DatePicker/">时间选择DatePicker</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E6%9C%8D%E5%8A%A1/">服务</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E6%9D%83%E9%99%90/">权限</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E6%9E%84%E5%BB%BA%E5%9F%BA%E7%B1%BB/">构建基类</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E6%B5%8B%E8%AF%95/">测试</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E7%9B%91%E5%90%AC%E9%94%81%E5%B1%8F/">监听锁屏</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E7%B3%BB%E7%BB%9F%E9%A1%B5%E9%9D%A2%E8%B7%B3%E8%BD%AC/">系统页面跳转</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E8%89%BA%E6%9C%AF%E6%8E%A2%E7%B4%A2/">艺术探索</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E8%AF%BB%E5%8F%96txt/">读取txt</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E8%BE%93%E5%85%A5%E6%B3%95/">输入法</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E9%9F%B3%E4%B9%90%E6%92%AD%E6%94%BE%E5%99%A8/">音乐播放器</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E9%BB%91%E9%A9%AC%E5%8D%AB%E5%A3%AB/">黑马卫士</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/Activity/" rel="tag">Activity</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Android-Studio/" rel="tag">Android Studio</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Android-Studio%E4%BB%8B%E7%BB%8D/" rel="tag">Android Studio介绍</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Android%E5%9F%BA%E7%A1%80/" rel="tag">Android基础</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Android%E6%A8%A1%E6%9D%BF/" rel="tag">Android模板</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/BaseRecyclerViewAdapterHelper/" rel="tag">BaseRecyclerViewAdapterHelper</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Bug%E9%97%AE%E9%A2%98/" rel="tag">Bug问题</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Button/" rel="tag">Button</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/EditText/" rel="tag">EditText</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Fragment/" rel="tag">Fragment</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Gradle/" rel="tag">Gradle</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ListView/" rel="tag">ListView</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/MD%E8%AF%AD%E6%B3%95/" rel="tag">MD语法</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/MyEclipse/" rel="tag">MyEclipse</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/OSS/" rel="tag">OSS</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/RecyclerView/" rel="tag">RecyclerView</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/SQL%E5%9F%BA%E7%A1%80/" rel="tag">SQL基础</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/UI%E6%8E%A7%E4%BB%B6/" rel="tag">UI控件</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/View/" rel="tag">View</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ViewPager/" rel="tag">ViewPager</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/View%E7%AF%87/" rel="tag">View篇</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/as%E6%8A%A5%E9%94%99/" rel="tag">as报错</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/jar%E5%8C%85/" rel="tag">jar包</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/targetSdkVersion/" rel="tag">targetSdkVersion</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E4%B8%83%E7%89%9B%E4%BA%91/" rel="tag">七牛云</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%8D%87%E7%BA%A7%E6%8A%A5%E9%94%99/" rel="tag">升级报错</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA/" rel="tag">博客搭建</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%9B%BE%E7%89%87%E5%A4%84%E7%90%86/" rel="tag">图片处理</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%A4%9A%E5%AA%92%E4%BD%93/" rel="tag">多媒体</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%B7%A5%E4%BD%9C%E9%97%AE%E9%A2%98/" rel="tag">工作问题</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%B9%BF%E6%92%AD%E6%9C%BA%E5%88%B6/" rel="tag">广播机制</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%BA%94%E7%94%A8%E8%AF%A6%E6%83%85/" rel="tag">应用详情</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%BE%AE%E5%8D%9A%E5%88%86%E4%BA%AB/" rel="tag">微博分享</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E6%8C%81%E4%B9%85%E5%8C%96%E5%AD%98%E5%82%A8/" rel="tag">持久化存储</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E6%9C%8D%E5%8A%A1/" rel="tag">服务</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E6%9D%83%E9%99%90/" rel="tag">权限</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E6%9E%84%E5%BB%BA%E5%9F%BA%E7%B1%BB/" rel="tag">构建基类</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E7%94%9F%E6%B4%BB/" rel="tag">生活</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E7%BB%83%E6%89%8B/" rel="tag">练手</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E8%89%BA%E6%9C%AF%E6%8E%A2%E7%B4%A2/" rel="tag">艺术探索</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E8%BE%93%E5%85%A5%E6%B3%95/" rel="tag">输入法</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E9%AB%98%E7%BA%A7%E6%8A%80%E5%B7%A7/" rel="tag">高级技巧</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/tags/Activity/" style="font-size: 12.5px;">Activity</a> <a href="/tags/Android-Studio/" style="font-size: 10px;">Android Studio</a> <a href="/tags/Android-Studio%E4%BB%8B%E7%BB%8D/" style="font-size: 12.5px;">Android Studio介绍</a> <a href="/tags/Android%E5%9F%BA%E7%A1%80/" style="font-size: 20px;">Android基础</a> <a href="/tags/Android%E6%A8%A1%E6%9D%BF/" style="font-size: 10px;">Android模板</a> <a href="/tags/BaseRecyclerViewAdapterHelper/" style="font-size: 10px;">BaseRecyclerViewAdapterHelper</a> <a href="/tags/Bug%E9%97%AE%E9%A2%98/" style="font-size: 10px;">Bug问题</a> <a href="/tags/Button/" style="font-size: 10px;">Button</a> <a href="/tags/EditText/" style="font-size: 10px;">EditText</a> <a href="/tags/Fragment/" style="font-size: 18.75px;">Fragment</a> <a href="/tags/Gradle/" style="font-size: 10px;">Gradle</a> <a href="/tags/ListView/" style="font-size: 17.5px;">ListView</a> <a href="/tags/MD%E8%AF%AD%E6%B3%95/" style="font-size: 11.25px;">MD语法</a> <a href="/tags/MyEclipse/" style="font-size: 13.75px;">MyEclipse</a> <a href="/tags/OSS/" style="font-size: 11.25px;">OSS</a> <a href="/tags/RecyclerView/" style="font-size: 12.5px;">RecyclerView</a> <a href="/tags/SQL%E5%9F%BA%E7%A1%80/" style="font-size: 10px;">SQL基础</a> <a href="/tags/UI%E6%8E%A7%E4%BB%B6/" style="font-size: 15px;">UI控件</a> <a href="/tags/View/" style="font-size: 10px;">View</a> <a href="/tags/ViewPager/" style="font-size: 10px;">ViewPager</a> <a href="/tags/View%E7%AF%87/" style="font-size: 10px;">View篇</a> <a href="/tags/as%E6%8A%A5%E9%94%99/" style="font-size: 10px;">as报错</a> <a href="/tags/jar%E5%8C%85/" style="font-size: 10px;">jar包</a> <a href="/tags/targetSdkVersion/" style="font-size: 10px;">targetSdkVersion</a> <a href="/tags/%E4%B8%83%E7%89%9B%E4%BA%91/" style="font-size: 10px;">七牛云</a> <a href="/tags/%E5%8D%87%E7%BA%A7%E6%8A%A5%E9%94%99/" style="font-size: 10px;">升级报错</a> <a href="/tags/%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA/" style="font-size: 12.5px;">博客搭建</a> <a href="/tags/%E5%9B%BE%E7%89%87%E5%A4%84%E7%90%86/" style="font-size: 15px;">图片处理</a> <a href="/tags/%E5%A4%9A%E5%AA%92%E4%BD%93/" style="font-size: 12.5px;">多媒体</a> <a href="/tags/%E5%B7%A5%E4%BD%9C%E9%97%AE%E9%A2%98/" style="font-size: 16.25px;">工作问题</a> <a href="/tags/%E5%B9%BF%E6%92%AD%E6%9C%BA%E5%88%B6/" style="font-size: 12.5px;">广播机制</a> <a href="/tags/%E5%BA%94%E7%94%A8%E8%AF%A6%E6%83%85/" style="font-size: 10px;">应用详情</a> <a href="/tags/%E5%BE%AE%E5%8D%9A%E5%88%86%E4%BA%AB/" style="font-size: 10px;">微博分享</a> <a href="/tags/%E6%8C%81%E4%B9%85%E5%8C%96%E5%AD%98%E5%82%A8/" style="font-size: 13.75px;">持久化存储</a> <a href="/tags/%E6%9C%8D%E5%8A%A1/" style="font-size: 12.5px;">服务</a> <a href="/tags/%E6%9D%83%E9%99%90/" style="font-size: 10px;">权限</a> <a href="/tags/%E6%9E%84%E5%BB%BA%E5%9F%BA%E7%B1%BB/" style="font-size: 10px;">构建基类</a> <a href="/tags/%E7%94%9F%E6%B4%BB/" style="font-size: 11.25px;">生活</a> <a href="/tags/%E7%BB%83%E6%89%8B/" style="font-size: 11.25px;">练手</a> <a href="/tags/%E8%89%BA%E6%9C%AF%E6%8E%A2%E7%B4%A2/" style="font-size: 10px;">艺术探索</a> <a href="/tags/%E8%BE%93%E5%85%A5%E6%B3%95/" style="font-size: 10px;">输入法</a> <a href="/tags/%E9%AB%98%E7%BA%A7%E6%8A%80%E5%B7%A7/" style="font-size: 11.25px;">高级技巧</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/11/">November 2017</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/10/">October 2017</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/09/">September 2017</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/08/">August 2017</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/07/">July 2017</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/06/">June 2017</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/04/">April 2017</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/03/">March 2017</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/02/">February 2017</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/09/">September 2016</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/10/">October 2014</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/04/">April 2014</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2013/01/">January 2013</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2012/05/">May 2012</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2017/11/03/Android%20Studio/Github%E4%B8%8A%E6%8F%90%E4%BA%A4%E4%BB%A3%E7%A0%81/">Github上提交代码</a>
          </li>
        
          <li>
            <a href="/2017/10/31/RecyclerView/BaseRecyclerViewAdapterHelper%E5%BA%93%E7%9A%84%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/">BaseRecyclerViewAdapterHelper库的基本使用方法</a>
          </li>
        
          <li>
            <a href="/2017/10/31/%E5%9B%BE%E7%89%87%E5%A4%84%E7%90%86/%E4%B8%83%E7%89%9B%E4%BA%91--%E4%B8%83%E7%89%9B%E4%BA%91%E5%BF%AB%E9%80%9F%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87/">七牛云快速上传图片</a>
          </li>
        
          <li>
            <a href="/2017/10/31/Gradle/Gradle--Gradle%E6%B7%BB%E5%8A%A0%E7%AC%AC%E4%B8%89%E6%96%B9%E5%BA%93%E6%8A%A5%E5%BC%82%E5%B8%B8/">Gradle添加第三方库报异常</a>
          </li>
        
          <li>
            <a href="/2017/10/26/Android%20Studio/%E8%A7%A3%E5%86%B3Android-Studio-Gradle-%E9%94%99%E8%AF%AF-%E7%BC%96%E7%A0%81GBK%E7%9A%84%E4%B8%8D%E5%8F%AF%E6%98%A0%E5%B0%84%E5%AD%97%E7%AC%A6/">解决Android Studio Gradle 错误 编码GBK的不可映射字符</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      
      &copy; 2021 wxyass<br>
      Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="/js/jquery-3.4.1.min.js"></script>



  
<script src="/fancybox/jquery.fancybox.min.js"></script>




<script src="/js/script.js"></script>





  </div>
</body>
</html>